const WebSocket = require('ws');
const {SerialPort} = require('serialport');
const _logs = require('../logs/index');
const JSON5 = require('json5');
const fs = require('fs');
const path = require('path');

/**
 * @description: 解析配置文件
 * @author: 王琛
 * @Date: 2025-09-03 17:21:23
 * @param {*}
 * @return {*}
 */
const configPath = path.resolve(__dirname, '../public/MainConfig.json5');

const MainConfig = () => JSON5.parse(fs.readFileSync(configPath, 'utf-8'));

module.exports.MainConfig = MainConfig;
/**
 * @description: 解析base64字符串为文件流的方法
 * @author: 王琛
 * @Date: 2023-09-19 10:54:24
 * @param {*}
 * @return {*}
 */
module.exports.AnalysisBase64 = ({Base64Str = "", type = 'coding'} = {}) => {

    if (!Base64Str) return;
    // 将Buffer对象转换为字符串并返回
    let str = ""
    // 判断是解密还是加密
    if (type === 'coding') {
        // 生成一个Buffer对象
        const buff = Buffer.from(Base64Str, 'utf-8');
        str = buff.toString('base64');
    } else if (type === 'decode') {
        const buff = Buffer.from(Base64Str, 'base64');
        str = buff.toString('utf-8');
    }
    return str;
}

/**
 * @method 获取客户端IP地址
 * @param {string} req 传入请求HttpRequest
 * 客户请求的IP地址存在于request对象当中
 * express框架可以直接通过 req.ip 获取
 */
module.exports.getClientIp = (req) => {
    return req.headers['x-forwarded-for'] ||
        req.ip ||
        req.connection.remoteAddress ||
        req.socket.remoteAddress ||
        req.connection.socket.remoteAddress ||
        '';
}


/**
 * @description: 自动重连的WebSocket客户端
 * @author: 王琛
 * @Date: 2025-09-03 11:45:56
 * @param {*}
 * @return {*}
 */

module.exports.AutoReconnectWebSocket = class AutoReconnectWebSocket {

    constructor({url, options = {}}) {
        this.url = url;
        this.options = options;
        this.reconnectInterval = options.reconnectInterval || 3000;
        this.maxRetries = options.maxRetries || Infinity;
        this.retryCount = 0;
        this.ws = null;
        this.connect();
    }

    connect() {
        this.ws = new WebSocket(this.url);

        this.ws.onopen = () => {
            this.retryCount = 0;
            if (this.options.onopen) this.options.onopen();
        };

        this.ws.onmessage = (event) => {
            if (this.options.onmessage) this.options.onmessage(event);
        };

        this.ws.onerror = (err) => {
            if (this.options.onerror) this.options.onerror(err);
        };

        this.ws.onclose = () => {
            if (this.options.onclose) this.options.onclose();
            if (this.retryCount < this.maxRetries) {
                setTimeout(() => {
                    this.retryCount++;
                    this.connect();
                    _logs.normal.error(`UeWebSoket断开连接,正在尝试重连${this.url}...`)

                }, this.reconnectInterval);
            }
        };
    }

    send(data) {

        _logs.normal.info("WebSocket发送数据:", data);

        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(data);
        }
    }

    close() {
        this.maxRetries = 0;
        if (this.ws) this.ws.close();
    }
}


/**
 * @description: 串口连接类
 * @author: 王琛
 * @Date: 2025-09-03 15:57:56
 * @param {*}
 * @return {*}
 */
module.exports.SerialPortManager = class SerialPortManager {
    constructor(options) {
        this.options = options;
        this.reconnectInterval = options.reconnectInterval || 3000;
        this.maxRetries = options.maxRetries || Infinity;
        this.retryCount = 0;
        this.port = null;
        this.connect();
    }

    connect() {
        this.port = new SerialPort(this.options);
        this.initListeners();
    }

    initListeners() {
        this.port.on('open', () => {
            _logs.normal.info("串口已打开");
            this.retryCount = 0;
            if (this.options?.Init) this.options?.Init()
        });

        this.port.on('data', (data) => {
            const _Str_Data = data.toString().trim();

            _logs.normal.info(`收到数据:${_Str_Data}`);

            this.options?.onmessage && this.options?.onmessage(_Str_Data);
        });

        this.port.on('error', (err) => {
            _logs.normal.error(`串口错误,${err.message}`);
            if (this.retryCount < this.maxRetries) {
                setTimeout(() => {
                    this.retryCount++;
                    _logs.normal.info(`尝试重连串口,第${this.retryCount}次`);
                    this.connect();
                }, this.reconnectInterval);
            } else {
                _logs.normal.error("重连次数已达上限，停止重连");
            }
        });

        this.port.on('close', () => {
            _logs.normal.error("串口已断开");
            if (this.retryCount < this.maxRetries) {
                setTimeout(() => {
                    this.retryCount++;
                    _logs.normal.info(`尝试重连串口,第${this.retryCount}次`);
                    this.connect();
                }, this.reconnectInterval);
            } else {
                _logs.normal.error("重连次数已达上限，停止重连");
            }
        });
    }

    send(data) {
        if (this.port && this.port.isOpen) {
            this.port.write(data, (err) => {
                if (err) {
                    _logs.normal.error(`串口错误:${err.message}`);
                } else {
                    _logs.normal.info(`串口发送数据:${data}`);
                }
            });
        } else {
            _logs.normal.error("串口未打开，无法发送数据");
        }
    }

    close() {
        this.maxRetries = 0;
        if (this.port) this.port.close();
    }
}
